package com.nuanshui.heatedloan.baseservice.service;

import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSON;
import com.google.common.collect.Lists;
import com.nuanshui.framework.res.qiniu.Qiniu;
import com.nuanshui.framework.springContext.SpringContextUtil;
import com.nuanshui.heatedloan.baseservice.constant.MediaBizType;
import com.nuanshui.heatedloan.baseservice.constant.MediaTextStyle;
import com.nuanshui.heatedloan.baseservice.constant.MediaType;
import com.nuanshui.heatedloan.baseservice.constant.String2MediaTextConverType;
import com.nuanshui.heatedloan.baseservice.dal.mapper.MediaMapper;
import com.nuanshui.heatedloan.baseservice.facade.MediaService;
import com.nuanshui.heatedloan.baseservice.facade.String2MediaTextConvert;
import com.nuanshui.heatedloan.baseservice.form.MediaForm;
import com.nuanshui.heatedloan.baseservice.vo.MediaVO;
import com.nuanshui.heatedloan.constant.DubboCacheRegion;
import com.nuanshui.heatedloan.constant.GlobalParam;
import com.nuanshui.heatedloan.constant.ServiceConstant;
import com.nuanshui.heatedloan.constant.TransactionManagerType;
import com.nuanshui.heatedloan.dubbo.extension.cache.manager.DubboCacheManager;
import com.nuanshui.heatedloan.dubbo.extension.cache.util.CachekeyUtil;
import com.nuanshui.heatedloan.enums.FileBelong;
import com.nuanshui.heatedloan.userinfo.tool.UserTool;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Field;
import java.util.*;



@Service(ServiceConstant.MEDIASERVICE)
@Transactional(readOnly=true,  value = TransactionManagerType.BASE_SERVICE_TRANSACTION_MANAGER)
public class MediaServiceImpl  extends CommonServiceImpl implements MediaService,InitializingBean{

	@Autowired
	private MediaMapper mediaMapper;
	
	@Autowired
	private DubboCacheManager dubboCacheManager;
	
	@Autowired
	private Qiniu qiniu;

	@Autowired
	private String2MediaTextConvert string2MediaTextConvert;
	
	private MediaService mediaService;//为了走代理，这里使用一个引用
	
	private Field[] fields;
	
	private MediaService getMediaService(){
		if(mediaService == null){
			mediaService = SpringContextUtil.getBean(MediaService.class);
		}
		return mediaService;
	}
	
	@Reference(url=GlobalParam.USER_DUBBO_SERVER,timeout=GlobalParam.DUBBO_SERVER_TIME_OUT,version=GlobalParam.USER_DUBBO_SERVER_VERSION)
	private UserTool userTool;
	
	@Override
	@Transactional(readOnly=false,value=TransactionManagerType.BASE_SERVICE_TRANSACTION_MANAGER)
	public void save(String mediaStr, int mediaBizType,String mediaBizId){

		List<MediaForm> forms = JSON.parseArray(mediaStr,MediaForm.class);
		save(forms,mediaBizType,mediaBizId);
	}

	@Override
	@Transactional(readOnly=false,value=TransactionManagerType.BASE_SERVICE_TRANSACTION_MANAGER)
	public void save(MediaForm form){
		List<MediaForm> list=new ArrayList<MediaForm>();
		list.add(form);
		save(list, form.getBizType(), form.getBizId(), 0);
	}

	@Override
	@Transactional(readOnly=false,value=TransactionManagerType.BASE_SERVICE_TRANSACTION_MANAGER)
	public void save(List<MediaForm> forms, int mediaBizType,String mediaBizId){
		save(forms, mediaBizType, mediaBizId, 0);
	}

	@Transactional(readOnly=false,value=TransactionManagerType.BASE_SERVICE_TRANSACTION_MANAGER)
	private void save(List<MediaForm> forms, int mediaBizType,String mediaBizId, Integer sortNum) {

		String bucketName =  null;
		String videoLocalKey = null;

		Set<String> cacheRegion = new HashSet<String>();
		for(MediaForm form :forms) {
			form.setSortNum(sortNum);
			form.setBizId(mediaBizId);
			form.setBizType(mediaBizType);
			if(form.getType() == MediaType.TEXT ){
				changeType(form);//如果是text，则判断是否是段落
			}
			switch (form.getType()) {
				case MediaType.TEXT://普通文本
					mediaMapper.insertMediaText(form);
					cacheRegion.add(DubboCacheRegion.CACHE_CONSTANT_MEDIA_TEXT);
					break;
				case MediaType.VIDEO://视频

					bucketName = qiniu.genBucketName(FileBelong.VIDEO);// image1变为video
					videoLocalKey = qiniu.qiniuKeyToLocalKey(form.getVideoKey(), bucketName);
					form.setVideoKey(videoLocalKey);

					bucketName = qiniu.genBucketName(FileBelong.PRODUCT);// image1变为video
					videoLocalKey = qiniu.qiniuKeyToLocalKey(form.getVideoImageKey(), bucketName);

					form.setVideoImageKey(videoLocalKey);

					mediaMapper.insertMediaVideo(form);
					cacheRegion.add(DubboCacheRegion.CACHE_CONSTANT_MEDIA_VIDEO);
					break;
				case MediaType.IMAGE://图片
					bucketName = qiniu.genBucketName(FileBelong.PRODUCT);// image1变为video
					videoLocalKey = qiniu.qiniuKeyToLocalKey(form.getImgKey(), bucketName);
					form.setImgKey(videoLocalKey);
					form.setBelong(FileBelong.PRODUCT);
					mediaMapper.insertMediaImage(form);
					cacheRegion.add(DubboCacheRegion.CACHE_CONSTANT_MEDIA_IMAGE);
					break;
				case MediaType.VOICE://音频

					bucketName = qiniu.genBucketName(FileBelong.PRODUCT);// image1变为video
					videoLocalKey = qiniu.qiniuKeyToLocalKey(form.getVoiceKey(), bucketName);
					form.setVoiceKey(videoLocalKey);
					mediaMapper.insertMediaVoice(form);
					cacheRegion.add(DubboCacheRegion.CACHE_CONSTANT_MEDIA_VOICE);
					break;
				case MediaType.HTML://html
					mediaMapper.insertMediaHtml(form);
					cacheRegion.add(DubboCacheRegion.CACHE_CONSTANT_MEDIA_HTML);
					break;

				case MediaType.PARAGRAPH_TEXT://如果是段落文本，则进行切割保存
					String contentText = form.getContentText();
					String[] contents = contentText.split("\n");//使用换行符切割
					if(contents.length == 0) return;
					//判断段落的样式，如果是1231 abc则直接添加
					MediaTextStyle mediaTextStyle = JSON.parseObject(form.getStyle(), MediaTextStyle.class);

					if(mediaTextStyle != null){
						Integer type = mediaTextStyle.getParagraphIconType();
						if(type == 1 || type == 2){//1是123，2是abc
							Integer paragraphNum = (type == 1)? 1 : 97;// 97是a
							for(String content : contents){
								String paragraphPrefix = getParagraphPrefix(paragraphNum,type);//得到段落排序
								MediaForm tempForm = string2MediaTextConvert.string2MediaFormConvert(paragraphPrefix + ". " +content, String2MediaTextConverType.CONVERT_TYPE_NOSTYLE);
								mediaTextStyle.setParagraphIconType(null);
								tempForm.setStyle(JSON.toJSONString(mediaTextStyle));
								tempForm.setBizType(mediaBizType);
								tempForm.setBizId(mediaBizId);
								tempForm.setSortNum(sortNum);
								tempForm.setType(MediaType.TEXT);
								mediaMapper.insertMediaText(tempForm);
								sortNum ++;
								paragraphNum ++;

							}
						}
						else if(type == 3){//否则，就是加上一个小圆点的样式
							for(String content : contents){
								MediaForm tempForm = string2MediaTextConvert.paragraphString2MediaFormConvert(content, form.getStyle());
								tempForm.setBizType(mediaBizType);
								tempForm.setBizId(mediaBizId);
								tempForm.setSortNum(sortNum);
								tempForm.setType(MediaType.TEXT);
								mediaMapper.insertMediaText(tempForm);
								sortNum ++;
							}
						}

					}
					continue;//这里要结束本次循环，因为在最后的一次sortNum++了，这里不结束，就又会++一次。
				default:
					break;
			}
			sortNum++;
		}

		//清除缓存
		for(String region : cacheRegion){
			dubboCacheManager.evictCache(region, CachekeyUtil.getCachekey(mediaBizId, mediaBizType));
		}
	}
	
	@Override
	public List<MediaForm> loadDefaultMediaTextByBizType(Integer mediaBizType){
		List<MediaForm> mediaList = mediaMapper.loadDefaultMediaTextByBizType(mediaBizType);
		for(MediaForm item : mediaList){
			item.setType(MediaType.TEXT);
		}
		return mediaList;
	}
	
	
	/**
	 * 如果是text，判断是否是段落
	 * @author Gonzo
	 * @date 2016年12月15日下午5:02:52
	 * @param form
	 * @since 1.0.0
	 */
	private void changeType(MediaForm form) {
		if(form.getStyle() == null) return ;
		MediaTextStyle mediaTextStyle = JSON.parseObject(form.getStyle(), MediaTextStyle.class);
		if(mediaTextStyle.getParagraphIconType() != null && mediaTextStyle.getParagraphIconType() != 0){
			form.setType(MediaType.PARAGRAPH_TEXT);
		}
	}


	/**
	 * 得到段落前缀
	 * @author Gonzo
	 * @date 2016年12月9日下午2:11:44
	 * @param paragraphNum
	 * @param type
	 * @return
	 * @since 1.0.0
	 */
	private String getParagraphPrefix(Integer paragraphNum, Integer type) {
		
		if(type == 1){
			return paragraphNum+"";
		}else{
			if(paragraphNum > 123)
				paragraphNum = 97;
			return ((char)(paragraphNum.intValue())) + "";
		}
	}


	@Override
	public List<MediaVO> listAllMedia(String bizId, int bizType) {
		
		return listMedia(bizId, bizType);
	}

	
	private  int[]  getAllMediaType(){
		int result[] = null;
		try {
			Field[] fields = getMediaFields();
			result = new int[fields.length];
			int i = 0;
			for(Field field :fields) {
				int value = Integer.valueOf(String.valueOf(field.get(MediaType.class)));
				result[i] = value;
				i++;	
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		return result;
		
	}
	
	@Override
	public List<MediaVO> listMediaByNotWhantType(String bizId, int bizType, Integer... mediaTypes){
		int[] types = getMediaTypeByNotWant(mediaTypes);
		return listMedia(bizId, bizType, types);
	}
	
	
	private int[] getMediaTypeByNotWant(Integer... mediaTypes){
		List<Integer> medias = new ArrayList<Integer>();
		Collections.addAll(medias, mediaTypes);
		
		int result[] = null;
		try{
			Field[] fields = getMediaFields();
			result = new int[fields.length-mediaTypes.length];
			int i = 0;
			for(Field field :fields){
				int value = Integer.valueOf(String.valueOf(field.get(MediaType.class)));
				if(!medias.contains(value)){
					result[i] = value;
					i++;
				}
			}
		
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		return result;
	}
	
	//不要每一次都防反射，这里可以缓存起来
	@SuppressWarnings("rawtypes")
	private Field[] getMediaFields(){
		if(fields == null || fields.length == 0){
			Class clazz = MediaType.class;
			fields = clazz.getDeclaredFields();
		}
		return fields;
	}

	@Override
	public List<MediaVO> listMedia(String bizId, int bizType, int... mediaTypes) {
		if(mediaTypes.length<=0) {//表示获取所有的
			mediaTypes = getAllMediaType();
		}
		List<MediaVO> mediaVOs = Lists.newArrayList();
		List<MediaVO> item = null;
		for(int mediaType :mediaTypes) {
			switch (mediaType) {
				case MediaType.TEXT://普通文本
					item = getMediaService().loadTextByBizIdAndBizType(bizId, bizType);		    
					break;
				case MediaType.VIDEO://视频
					 item = getMediaService().loadVideoByBizIdAndBizType(bizId, bizType);
					break;			
				case MediaType.IMAGE://图片
		            item = getMediaService().loadImageByBizIdAndBizType(bizId, bizType);
					break;
				case MediaType.VOICE://音频
				   item = getMediaService().loadVoiceByBizIdAndBizType(bizId, bizType);
						break;
				case MediaType.HTML://html	
					item = getMediaService().loadHtmlByBizIdAndBizType(bizId, bizType);
						break;
				default:
					break;
			}
			
			if(item!=null && item.size()>0) {
				for(MediaVO vo :item) {
					vo.setType(mediaType);
					mediaVOs.add(vo);
				}
				item = null;
			}
			
		}		
		Collections.sort(mediaVOs);
		return mediaVOs;
	}
	
	@Override
	@Transactional(readOnly=false,value=TransactionManagerType.BASE_SERVICE_TRANSACTION_MANAGER)
	public void deleteMedia(String mediaBizId, int mediaBizType, int... mediaTypes) {
		if(mediaTypes.length<=0) {//表示获取所有的
			mediaTypes = getAllMediaType();
		}
		
		Set<String> cacheRegion = new HashSet<String>();
		for(int mediaType :mediaTypes) {
			switch (mediaType) {
				case MediaType.TEXT://普通文本
					getMediaService().deleteMediaText(mediaBizId, mediaBizType);
					cacheRegion.add(DubboCacheRegion.CACHE_CONSTANT_MEDIA_TEXT);
					break;
				case MediaType.VIDEO://视频
					getMediaService().deleteMediaVideo(mediaBizId, mediaBizType);
					cacheRegion.add(DubboCacheRegion.CACHE_CONSTANT_MEDIA_VIDEO);
					break;			
				case MediaType.IMAGE://图片
					getMediaService().deleteMediaImage(mediaBizId, mediaBizType);
					cacheRegion.add(DubboCacheRegion.CACHE_CONSTANT_MEDIA_IMAGE);
					break;
				case MediaType.VOICE://音频
					getMediaService().deleteMediaVoice(mediaBizId, mediaBizType);
					cacheRegion.add(DubboCacheRegion.CACHE_CONSTANT_MEDIA_VOICE);
					break;
				case MediaType.HTML://html	
					getMediaService().deleteMediaHtml(mediaBizId, mediaBizType);
					cacheRegion.add(DubboCacheRegion.CACHE_CONSTANT_MEDIA_HTML);
					break;
				default:
					break;
			}
		}
		
		//清除缓存
		for(String region : cacheRegion){
			dubboCacheManager.evictCache(region, CachekeyUtil.getCachekey(mediaBizId, mediaBizType));
		}
	}
	
	
	@Override
	public List<MediaVO> loadTextByBizIdAndBizType(String bizId, int bizType){
		return mediaMapper.loadTextByBizIdAndBizType(bizId, bizType);
	}
	
	@Override
	public List<MediaVO> loadVideoByBizIdAndBizType(String bizId, int bizType){
		return mediaMapper.loadVideoByBizIdAndBizType(bizId, bizType);
	}
	
	@Override
	public List<MediaVO> loadImageByBizIdAndBizType(String bizId, int bizType){
		return mediaMapper.loadImageByBizIdAndBizType(bizId, bizType);
	}
	
	@Override
	public List<MediaVO> loadVoiceByBizIdAndBizType(String bizId, int bizType){
		return mediaMapper.loadVoiceByBizIdAndBizType(bizId, bizType);
	}
	
	@Override
	public List<MediaVO> loadHtmlByBizIdAndBizType(String bizId, int bizType){
		return mediaMapper.loadHtmlByBizIdAndBizType(bizId, bizType);
	}
	
	@Override
	@Transactional(readOnly=false,value=TransactionManagerType.BASE_SERVICE_TRANSACTION_MANAGER)
	public void deleteMediaText(String mediaBizId, int mediaBizType){
		mediaMapper.deleteMediaText(mediaBizType, mediaBizId);
	}
	
	@Override
	@Transactional(readOnly=false,value=TransactionManagerType.BASE_SERVICE_TRANSACTION_MANAGER)
	public void deleteMediaVideo(String mediaBizId, int mediaBizType){
		mediaMapper.deleteMediaVideo(mediaBizType, mediaBizId);
	}

	@Override
	@Transactional(readOnly=false,value=TransactionManagerType.BASE_SERVICE_TRANSACTION_MANAGER)
	public void deleteMediaImage(String mediaBizId, int mediaBizType){
		mediaMapper.deleteMediaImage(mediaBizType, mediaBizId);
	}
	
	@Override
	@Transactional(readOnly=false,value=TransactionManagerType.BASE_SERVICE_TRANSACTION_MANAGER)
	public void deleteMediaVoice(String mediaBizId, int mediaBizType){
		mediaMapper.deleteMediaVoice(mediaBizType, mediaBizId);
	}
	
	@Override
	@Transactional(readOnly=false,value=TransactionManagerType.BASE_SERVICE_TRANSACTION_MANAGER)
	public void deleteMediaHtml(String mediaBizId, int mediaBizType){
		mediaMapper.deleteMediaHtml(mediaBizType, mediaBizId);
	}
	
	
	@Override
	public MediaVO findFirstMedia(String bizId, int bizType, int... mediaTypes){
		List<MediaVO> mediaVOs = getMediaService().listMedia(bizId, bizType, mediaTypes);
		if(mediaVOs != null && !mediaVOs.isEmpty()){
			return mediaVOs.get(0);
		}
		return null;
	}

	@Override
	public void updateMedia(MediaVO item)
	{
		mediaMapper.updateMedia(item);
		dubboCacheManager.evictCache(DubboCacheRegion.CACHE_CONSTANT_MEDIA_HTML, CachekeyUtil.getCachekey(item.getBizId(), item.getBizType()));
	}
	
	@Override
	public void afterPropertiesSet() throws Exception {
		/*List<MediaForm> vos = Lists.newArrayList();
		
		MediaForm image1 = new MediaForm();
	  
		image1.setImgKey("8D540EEB-866A-4DCE-9685-DD3BB7047BE4");
		image1.setWidth(790);
		image1.setHeight(600);
		
		image1.setCropx(0);
		image1.setCropy(0);
		image1.setCropWidth(790);
		image1.setCropHeight(600);
		image1.setType(MediaType.IMAGE);
		image1.setBizId(IdTypeHandler.encode(1));
		image1.setBelong(FileBelong.PRODUCT);
		
		MediaForm image2 = new MediaForm();
		
		
		image2.setImgKey("3edcebc3-20fa-45b2-bb4a-e93b11642591");
		image2.setWidth(1280);
		image2.setHeight(1280);
		image2.setType(MediaType.IMAGE);
		image2.setCropx(0);
		image2.setCropy(0);
		image2.setCropWidth(1280);
		image2.setCropHeight(1280);
		image2.setBizId(IdTypeHandler.encode(1));
		image2.setBelong(FileBelong.PRODUCT);
		
		
		vos.add(image1);
		vos.add(image2);
		
		
		MediaForm text = new MediaForm();
		
		text.setContentText("测试");
		text.setType(MediaType.TEXT);
		
		vos.add(text);
		
        MediaForm text2 = new MediaForm();		
		text2.setContentText("测试222");
		text2.setType(MediaType.TEXT);	
		vos.add(text2);
		
		
		MediaForm video = new MediaForm();
		
		video.setVideo("Test_457BA0A0-F556-4529-9520-AD7D1124973A");
		video.setType(MediaType.VIDEO);
		video.setVideoImage("Test_6E65BE98-9E1D-4C12-A25F-1F5C0AA2FFB8");
		vos.add(video);
			
		String mediaStr = JSON.toJSONString(vos);
		
		this.saveAndPush(mediaStr, MediaBizType.MUSEUM,IdTypeHandler.encode(1));*/
		
		
		/*
	    List<MediaVO> vos = listMedia(IdTypeHandler.encode(1),MediaBizType.MUSEUM,MediaType.TEXT);
		for(MediaVO vo :vos){
			System.out.println(vo.getType()+"  "+vo.getContentText());
		}*/
			
		
	}

	@Override
	@Transactional(readOnly=false,value=TransactionManagerType.BASE_SERVICE_TRANSACTION_MANAGER)
	public void updateMediaTest(MediaVO vo) {
		mediaMapper.updateMediaTest(vo);
		dubboCacheManager.evictCache(DubboCacheRegion.CACHE_CONSTANT_MEDIA_TEXT, vo.getBizId(), MediaBizType.MUSEUM_INFO);
	}

		
}
